<template>
  <el-row :gutter="20">
    <!-- 左侧部门树 -->
    <!-- <el-col :span="6" :xs="24">
      <ContentWrap class="h-1/1">
        <ReportDeptTree @node-click="handleDeptNodeClick" />
      </ContentWrap>
    </el-col> -->
    <el-col :span="24" :xs="24">
      <div style="height:70vh;border-color: red !important;" class="tree-container">
        <div>
          <el-button type="primary" @click="getDataByParentId(0)">
            <Icon icon="ep:search" class="mr-5px" />全部
          </el-button>
          <el-button type="primary" v-for="(item, index) in childList" :key="item.id || index"
            @click="getDataByParentId(item.id)">
            <Icon icon="ep:search" class="mr-5px" /> {{ item.name }}
          </el-button>

        </div>

        <vue3-tree-org :draggable="false" :node-draggable="false" :clone-node-drag="false"
          @on-node-drag-end="handleDragEnd" :line-style="{ stroke: '#e74c3c' }" ref="treeOrgRef" :props="props"
          :data="data" :define-menus="defineMenus" :default-expand-level="expandLevel" center :horizontal="horizontal"
          :collapsable="collapsable" :only-one-node="onlyOneNode" :filter-node-method="filterNodeMethod"
          :node-add="addNode" :node-delete="delNode" :node-edit="editNode" @on-node-click="onNodeClick"
          @on-node-contextmenu="handleNodeContext">
          <template #default="{ node }">
            <div class="custom-node" :class="{
              'has-link': node.$$data.url,
            }" :style="{ backgroundColor: node.$$data.color }" @mouseenter="hoverNode = node.id"
              @mouseleave="hoverNode = null">
              <div class="node-content">
                <div class="node-name">
                  <Icon :icon="node.$$data.icon" class="plus" />
                  {{ node.$$data.name }}
                </div>
                <div v-if="node.$$data.title" class="node-title">
                  {{ node.$$data.title }}
                </div>
              </div>

              <div v-if="node.$$data.url" class="node-link-hint">
                <el-icon :class="{ 'pulse': hoverNode === node.id }">
                  <Link />
                </el-icon>
              </div>
            </div>
          </template>
        </vue3-tree-org>
      </div>
    </el-col>
  </el-row>
  <ReportViewForm ref="reportDialogRef" @success="getOrgData()" />
</template>

<script lang="ts" name="treeView" setup>
import { ReportViewApi } from '@/api/business/reportview'
import { url } from 'inspector'
import { any } from 'vue-types'
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const ReportViewForm = defineAsyncComponent(() => import('./ReportViewForm.vue'))
import ReportDeptTree from './ReportDeptTree.vue'
// 定义org组件key-value定义
const props = reactive({
  id: 'id',
  pid: 'parentId',
  label: 'name',
  expand: 'expand',
  children: 'children',
  url: 'url'
})

const getDataByParentId = (id) => {
  queryParams.parentId = id
  getOrgData()

}

/**
 * 处理节点拖拽结束事件
 * @param from 被拖动的节点（源）
 * @param to 目标父节点
 */
const handleDragEnd = async (from, to) => {

  console.log("????????", from, to);


  // 防止拖到自己或根租户等非法操作
  if (from.id === to.id) {
    message.warning('不能将节点拖动到自身')
    await getOrgData() // 重置视图
    return
  }

  // 检查是否拖到根租户（id为0）等限制
  if (to.id === '0') {
    message.error(t('common.tenantNodeErrorText'))
    await getOrgData()
    return
  }

  try {
    // 准备更新数据：将 from 节点的 parentId 改为 to.id
    const updateData = {
      id: from.id,
      parentId: to.id
    }

    console.log("更新", updateData);


    // 调用 API 更新节点的上级
    await ReportViewApi.updateReportView(updateData)

    message.success(`已将 "${from.label}" 移动到 "${to.label}" 下`)

    // 刷新整棵树
    await getOrgData()
  } catch (err) {
    message.error('移动节点失败，请检查网络或权限')
    console.error('拖拽更新失败:', err)
    // 失败后刷新树结构，恢复视图
    await getOrgData()
  }
}

const data = reactive({
  id: '',
  parentId: '',
  name: '',
  icon: '',
  title: '',
  color: '',
  url: ''
})


// 定义org组件右键定义
const defineMenus = reactive([
  { name: '新增', command: 'add' },
  { name: '修改', command: 'edit' },
  { name: '删除', command: 'delete' }
])

const cloneNodeDrag = ref(true)
const collapsable = ref(false)
const expandLevel = ref(2) //默认展开层级
const horizontal = ref(false)
const onlyOneNode = ref(false)
const treeOrgRef = ref()
const reportDialogRef = ref()

/**
 * 过滤节点
 */
const filter = (deptName: string) => {
  treeOrgRef.value.filter(deptName)
}

/**
 * 节点过滤方法
 * @param {string} value 过滤条件
 * @param {object} data 节点数据
 * @returns {boolean} 返回过滤结果
 */
const filterNodeMethod = (value, data) => {
  if (!value) return true
  return data.label.indexOf(value) !== -1
}

/**
 * 处理展开/折叠树
 */
const handleExpand = async () => {
  collapsable.value = !collapsable.value
}

/**
 * 检查节点是否是根租户节点
 * @param {object} node 节点对象
 * @returns {boolean} 如果节点是根租户节点，返回true；否则返回false
 */
const checkNode = (node) => {
  if (node?.id === '0') {
    message.error(t('common.tenantNodeErrorText'))
    return false
  }
  return true
}

/**
 * 当用户左键点击节点
 * @param node
 */
const onNodeClick = (e, node: any) => {
  console.log('左键单击', node)

  // 检查是否存在有效URL
  if (node.url) {
    // 处理URL格式（自动补全http协议）
    // const formattedUrl = node.url.startsWith('http') ? node.url : `https://${node.url}`

    // 处理URL格式（自动补全https协议，并去除前后空格）
    const formattedUrl = node.url.trim().startsWith('http')
      ? node.url.trim()
      : `https://${node.url.trim()}`;

    // 新窗口打开（带安全限制解除）
    const newWindow = window.open('', '_blank')
    if (newWindow) {
      newWindow.opener = null  // 安全措施
      newWindow.location.href = formattedUrl
    } else {
      console.error('弹出窗口被浏览器阻止，请检查浏览器设置')
    }
  }
}

const handleNodeContext = (event: MouseEvent, nodeData: any, node: any, element: HTMLElement) => {
  // 阻止默认浏览器右键菜单
  event.preventDefault()

  const { clientX, clientY } = e
  const rightFun = new MouseEvent('contextmenu', {
    bubbles: true,
    cancelable: false,
    view: window,
    button: 2,
    buttons: 0,
    clientX,
    clientY
  })
  e.target.dispatchEvent(rightFun)
  console.log('右键点击节点:', nodeData)
}

/**
 * 添加部门
 * @param {object} node 节点对象
 */
const addNode = (node) => {
  reportDialogRef.value.open('create', node?.id)
}

/**
 * 编辑部门
 * @param {object} node 节点对象
 */
const editNode = (node) => {
  if (!checkNode(node)) {
    return
  }
  reportDialogRef.value.open('edit', node?.id)
}


/**
 * 删除部门
 * @param {object} node 节点对象
 */
const delNode = async (node) => {
  if (!checkNode(node)) {
    return
  }

  try {
    // 删除的二次确认
    await message.delConfirm()
    // 发起删除
    await ReportViewApi.deleteReportView(node.id)
    message.success(t('common.delSuccess'))
    // 刷新数据
    await getOrgData()
  } catch (err: any) {

  }

}

const queryParams = reactive({
  name: undefined,
  parentId: undefined
})
/** 处理部门被点击 */
const handleDeptNodeClick = async (row: any) => {
  if (row === undefined) {
    queryParams.parentId = undefined
    await getOrgData()
  } else {
    queryParams.parentId = row.id
    await getOrgData()
  }
}

const childList = ref([])
const getInitData = async () => {
  const data = await ReportViewApi.getReportViewList(queryParams)
  childList.value = data
  console.log("ccccc", childList.value);


}

/**
 * 查询部门数据
 */
const getOrgData = async () => {
  // 查询当前租户信息

  // const tenant = await getObj(Session.getTenant())
  await ReportViewApi.reportTree(queryParams).then((res) => {
    //// 执行赋值逻辑
    const rootNode = res[0] // 取第一个节点作为根

    // 1. 把 res[0] 的基本信息赋值给 reactive 对象 data
    Object.assign(data, {
      id: rootNode.id,
      parentId: rootNode.parentId,
      name: rootNode.name,
      icon: rootNode.icon,
      title: rootNode.title,
      color: rootNode.color,
      url: rootNode.url,
    })

    data.children = res[0].children

  })
}

onMounted(() => {
  getOrgData()
  getInitData()
})

// 暴露变量
defineExpose({
  getOrgData,
  handleExpand,
  filter
})
</script>



<style>
.tree-container {
  background: linear-gradient(135deg, #f5f7fa 0%, #e4efe9 100%);
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
}

.custom-node {
  background: white;
  border-radius: 10px;
  padding: 14px 18px;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.08);
  border: 1px solid #e1e5eb;
  transition: all 0.3s ease;
  position: relative;
  min-width: 180px;
  display: flex;
  flex-direction: column;
}

.custom-node:hover {
  transform: translateY(-3px);
  box-shadow: 0 6px 15px rgba(66, 153, 225, 0.25);
  border-color: #c2d9f0;
}

.has-link {
  border-left: 14px solid #4299e1;
  cursor: pointer;
}

.has-link:hover {
  background-color: #f0f7ff;
}

.highlight-node {
  background: linear-gradient(135deg, #ebf4ff 0%, #d5e8ff 100%);
  border: 1px solid #a3c7f7;
}

.node-content {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.node-name {
  font-size: 16px;
  font-weight: 600;
  color: #2d3748;
  align-items: center;
  gap: 8px;
}

.node-title {
  font-size: 13px;
  color: #718096;
  font-style: italic;
  padding-top: 4px;
  border-top: 1px dashed #e2e8f0;
}

.node-icon {
  color: #4299e1;
  font-size: 18px;
}

.node-link-hint {
  position: absolute;
  top: -10px;
  right: -10px;
  background: #4299e1;
  color: white;
  border-radius: 50%;
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 2px 5px rgba(66, 153, 225, 0.5);
  transition: all 0.3s ease;
}

/* 链接提示动画 */
.pulse {
  animation: pulse-animation 1.5s infinite;
}

@keyframes pulse-animation {
  0% {
    transform: scale(1);
  }

  50% {
    transform: scale(1.2);
  }

  100% {
    transform: scale(1);
  }
}


/* 如果连接线是使用边框实现的 */
.tree-org-node__children::before,
.tree-org-node__line::before {
  border-color: transparent !important;
  border-left: 2px solid rgb(32, 31, 31) !important;
  /* 真正的连接线 */
  border-width: 20px 0 0 2px !important;
  /* 控制方向和长度 */
}


/* 水平连接线（兄弟节点之间的横线）*/
.tree-org-node:not(:first-child):before,
.tree-org-node:not(:last-child):after {
  border-top: 2px solid #1f1e1e;
  /* 红色横线 */
}

/* 垂直连接线（从父节点下来的竖线）*/
.tree-org-node:after {
  left: 50%;
  border-left: 2px solid #141313;
  /* 红色竖线 */
}


.zoom-container.is-center {
  transform: scale(0.6);
  transform-origin: 0 0;
  width: 166.667%;
  /* = 100% / 0.6 */
  height: 166.667%;
  overflow-x: auto;
  position: relative;
}

.draggable.zm-draggable {
  /* 如果它用了绝对定位，确保相对于 .zoom-container */
  position: relative;
  /* 或 absolute，视情况而定 */
}

.draggable.zm-draggable {}

.zm-tree-org .zoom-container.is-center {
  display: flex;
  justify-content: left
}
</style>
